# serializers.py
from django.utils import timezone
from rest_framework import serializers, fields
from .models import Product, Inventory, SalesRecord, Dish
from django.db.models import Sum, ExpressionWrapper, F
from datetime import datetime, timedelta


class ProductReportSerializer(serializers.ModelSerializer):
    latest_price = serializers.SerializerMethodField()
    price_change = serializers.SerializerMethodField()
    price_change_percentage = serializers.SerializerMethodField()
    purchase_quantity = serializers.SerializerMethodField()
    purchase_amount = serializers.SerializerMethodField()
    current_stock = serializers.SerializerMethodField()

    class Meta:
        model = Product
        fields = [
            # id
            'product_id',
            # 名称
            'name',
            # 最新价格
            'latest_price',
            # 涨跌价格
            'price_change',
            # 涨跌幅度
            'price_change_percentage',
            # 采购数量（克重）
            'purchase_quantity',
            # 采购金额
            'purchase_amount',
            # 库存
            'current_stock']

    def get_latest_price(self, obj):
        print("这个对象打印：", obj)
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        print('123123', created_at_date)
        # 通过上下文获取过滤后的产品列表
        filtered_products = self.context.get('filtered_products')
        print('视图类过滤的货品:', filtered_products)
        latest_inventory = Inventory.objects.filter(
            product=obj,
            created_at__date=created_at_date,
            stock_out_quantity__isnull=True,  # stock_out_quanitiy 为 None
            product_price__isnull=False,  # product_price 不为 None
        ).order_by('-created_at').first()

        if latest_inventory:
            return latest_inventory.product_price
        else:
            return None

    def get_price_change(self, obj):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        latest_inventory = Inventory.objects.filter(
            product=obj,
            created_at__date__lte=created_at_date,
            stock_out_quantity__isnull=True,  # stock_out_quanitiy 不为 None
            product_price__isnull=False,  # product_price 不为 None
        ).order_by('-created_at').first()
        previous_inventory = Inventory.objects.filter(
            product=obj,
            created_at__date__lt=created_at_date,
            stock_out_quantity__isnull=True,  # stock_out_quanitiy 不为 None
            product_price__isnull=False,  # product_price 不为 None
        ).order_by('-created_at').first()

        if latest_inventory and previous_inventory and \
                latest_inventory.product_price is not None and \
                previous_inventory.product_price is not None:
            return latest_inventory.product_price - previous_inventory.product_price
        else:
            return None

    def get_price_change_percentage(self, obj):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        latest_inventory = Inventory.objects.filter(
            product=obj,
            created_at__date__lte=created_at_date,
            stock_out_quantity__isnull=True,  # stock_out_quanitiy 不为 None
            product_price__isnull=False,  # product_price 不为 None
        ).order_by('-created_at').first()
        previous_inventory = Inventory.objects.filter(
            product=obj,
            created_at__date__lt=created_at_date,
            stock_out_quantity__isnull=True,  # stock_out_quanitiy 不为 None
            product_price__isnull=False,  # product_price 不为 None
        ).order_by('-created_at').first()

        if latest_inventory and previous_inventory and \
                latest_inventory.product_price is not None and \
                previous_inventory.product_price is not None and \
                previous_inventory.product_price != 0:
            price_difference = latest_inventory.product_price - previous_inventory.product_price
            percentage_change = (price_difference / previous_inventory.product_price) * 100
            return f"{percentage_change:.2f}%"
        else:
            return None

    def get_purchase_quantity(self, obj):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        queryset = Inventory.objects.filter(
            product=obj,
            created_at__date=created_at_date,
            stock_out_quantity__isnull=True,  # stock_out_quanitiy 不为 None
            product_price__isnull=False,  # product_price 不为 None
            # ).aggregate(purchase_quantity=Sum('weight'))['purchase_quantity'] or 0)
        )
        total_purchase_quantity = 0
        for item in queryset:
            product = item.product
            if (item.product_price is not None) and (item.before_weight is not None) and (
                        item.quantity is not None):
                if product and product.unit.name != '克' and product.unit.unit_type == 2:
                    purchase_quantity = float(item.before_weight) * float(item.quantity)
                else:
                    purchase_quantity = float(item.product_price) * float(item.quantity)
                total_purchase_quantity += purchase_quantity
            else:
                # 如果有任何一个值为 None，则跳过这次循环
                continue
        return total_purchase_quantity

    def get_purchase_amount(self, obj):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        queryset = Inventory.objects.filter(
            product=obj,
            created_at__date=created_at_date,
            stock_out_quantity__isnull=True,  # stock_out_quanitiy 不为 None
            product_price__isnull=False,  # product_price 不为 None
            # ).aggregate(purchase_amount=Sum('product_price'))['purchase_amount'] or 0
        )

        total_purchase_amount = 0
        for item in queryset:
            product = item.product
            if (item.product_price is not None) and (item.before_weight is not None) and (item.quantity is not None):
                if product and product.unit.name != '克' and product.unit.unit_type == 2:
                    purchase_amount = float(item.product_price) * float(item.before_weight) * float(item.quantity)
                else:
                    purchase_amount = float(item.product_price) * float(item.quantity)
                total_purchase_amount += purchase_amount
            else:
                # 如果有任何一个值为 None，则跳过这次循环
                continue
        return total_purchase_amount

    def get_current_stock(self, obj):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        latest_inventory = Inventory.objects.filter(
            product=obj,
            # created_at__date__lte=created_at_date,
        ).order_by('-created_at').first()
        print(111, latest_inventory)
        return latest_inventory.current_stock if latest_inventory else 0


class DishReportSerializer(serializers.ModelSerializer):
    dish_name = serializers.CharField(source='dish.name', read_only=True)
    latest_price = serializers.SerializerMethodField()
    price_change = serializers.SerializerMethodField()
    price_change_percentage = serializers.SerializerMethodField()
    total_sales_amount = serializers.SerializerMethodField()
    total_sales_quantity = serializers.SerializerMethodField()
    product_quantity = serializers.SerializerMethodField()
    product_quantity_info = serializers.SerializerMethodField()

    class Meta:
        model = SalesRecord
        fields = ['record_id',
                  # 名称
                  'dish',
                  'dish_name',
                  # 最新价格
                  'latest_price',
                  # 涨跌价格
                  'price_change',
                  #  涨跌幅度，
                  'price_change_percentage',
                  # 销售数量
                  'total_sales_amount',
                  # 销售金额
                  'total_sales_quantity',
                  # 关联的菜品数
                  'product_quantity',
                  # 关联菜品对应货品信息
                  'product_quantity_info']

    def get_latest_price(self, obj):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日

        latest_price_record = SalesRecord.objects.filter(
            dish=obj.dish,  # 根据菜品过滤
            created_at__date=created_at_date
        ).order_by('-created_at').first()

        if latest_price_record:
            return latest_price_record.dish_price
        else:
            return None

    # lte: 是 "less than or equal to" 的缩写，表示小于或等于指定的值。
    def get_price_change(self, obj):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        # if obj.sales_date is None:
        #     print("obj.sales_date is None")
        #     return None
        print(created_at_date, (obj.created_at.date() - timedelta(days=1)))
        latest_sales_record = SalesRecord.objects.filter(
            dish=obj.dish,
            # created_at__date=created_at_date,
            created_at__date__lte=created_at_date,
        ).order_by('-created_at').first()
        previous_sales_record = SalesRecord.objects.filter(
            dish=obj.dish,
            created_at__date__lte=(obj.created_at.date() - timedelta(days=1))
        ).first()
        print('最新价格', latest_sales_record, '最新的上一条:', previous_sales_record)

        if latest_sales_record and previous_sales_record and \
                latest_sales_record.dish_price is not None and \
                previous_sales_record.dish_price is not None:
            return float(latest_sales_record.dish_price) - float(previous_sales_record.dish_price)
        else:
            return None

    def get_price_change_percentage(self, obj):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        latest_sales_record = SalesRecord.objects.filter(
            dish=obj.dish,
            created_at__date__lte=created_at_date,
        ).order_by('-created_at').first()
        previous_sales_record = SalesRecord.objects.filter(
            dish=obj.dish,
            created_at__date__lte=(obj.created_at.date() - timedelta(days=1))
        ).first()

        if previous_sales_record and latest_sales_record \
                and latest_sales_record.dish_price != 0 and previous_sales_record.dish_price != 0:
            print(latest_sales_record, previous_sales_record)
            price_difference = latest_sales_record.dish_price - previous_sales_record.dish_price
            percentage_change = (price_difference / previous_sales_record.dish_price) * 100
            return f"{percentage_change:.2f}%"
        else:
            return None

    def get_total_sales_amount(self, obj):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        total_sales_amount_today = SalesRecord.objects.filter(
            dish=obj.dish,
            created_at__date=created_at_date
        ).aggregate(total_sales=Sum('dish_price'))['total_sales']
        return total_sales_amount_today

    def get_total_sales_quantity(self, obj):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        total_sales_quantity_today = SalesRecord.objects.filter(
            dish=obj.dish,
            created_at__date=created_at_date
        ).aggregate(total_quantity=Sum('sales_quantity'))['total_quantity']
        return total_sales_quantity_today

    def get_product_quantity(self, obj):
        print(obj)
        if obj.dish is None:
            return None
        # Replace with logic to get the quantity of products associated with the dish
        else:
            product_quantity = obj.dish.products.count()
            return product_quantity

    def get_product_quantity_info(self, obj):
        print(obj)
        if obj.dish is None:
            return None
        # Replace with logic to get the quantity of products associated with the dish
        else:
            product_info = []
            now = timezone.now()
            for product in obj.dish.products.all():
                latest_inventory = product.inventory.filter(created_at__lte=now).order_by('-created_at').first()
                if latest_inventory:
                    product_info.append({
                        "name": product.name,
                        "stock": latest_inventory.current_stock
                    })

            return product_info


class PurchaseAmountQuantitySerializer(serializers.Serializer):
    today_purchase_amount = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)
    today_purchase_count = serializers.IntegerField(read_only=True)
    yesterday_purchase_amount = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)
    yesterday_purchase_count = serializers.IntegerField(read_only=True)
    last_week_purchase_amount = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)
    last_week_purchase_count = serializers.IntegerField(read_only=True)
    current_month_purchase_amount = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)

    def to_representation(self, instance):
        today_purchase_amount, today_purchase_count = self.get_today_purchase_summary(instance)
        yesterday_purchase_amount, yesterday_purchase_count = self.get_yesterday_purchase_summary(instance)
        last_week_purchase_amount, last_week_purchase_count = self.get_last_week_purchase_summary(instance)
        current_month_purchase_amount = self.get_current_month_purchase_summary(instance)

        return {
            'today_purchase_amount': today_purchase_amount,
            'today_purchase_count': today_purchase_count,
            'yesterday_purchase_amount': yesterday_purchase_amount,
            'yesterday_purchase_count': yesterday_purchase_count,
            'last_week_purchase_amount': last_week_purchase_amount,
            'last_week_purchase_count': last_week_purchase_count,
            'current_month_purchase_amount': current_month_purchase_amount
        }

    def get_today_purchase_summary(self, instance):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        queryset = instance.filter(stock_in_time__date=created_at_date)
        # purchase_amount = queryset.aggregate(total_amount=Sum('product_price'))['total_amount'] or 0
        total_today_purchase_amount = 0
        for item in queryset:
            product = item.product
            print("|-----------------------------------------------------------------|")
            print("|"'货品数量:', item.quantity, "|", '货品名称:', product, "|", '货品单位名称:', product.unit.name,
                  "|", "货品类型id:",
                  product.unit.unit_type, "|")
            if (item.product_price is not None) and (item.before_weight is not None) and (item.quantity is not None):
                if product and product.unit.name != '克' and product.unit.unit_type == 2:
                    purchase_amount = float(item.product_price) * float(item.before_weight) * float(item.quantity)
                else:
                    purchase_amount = float(item.product_price) * float(item.quantity)
                total_today_purchase_amount += purchase_amount
            else:
                # 如果有任何一个值为 None，则跳过这次循环
                continue
        purchase_count = queryset.count()
        return total_today_purchase_amount, purchase_count

    def get_last_week_purchase_summary(self, instance):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        last_week_start = created_at_date - timedelta(days=created_at_date.weekday() + 7)
        last_week_end = last_week_start + timedelta(days=6)
        queryset = instance.filter(stock_in_time__date__range=[last_week_start, last_week_end])
        # purchase_amount = queryset.aggregate(total_amount=Sum('product_price'))['total_amount'] or 0
        total_last_week_purchase_amount = 0
        for item in queryset:
            product = item.product
            print("|-----------------------------------------------------------------|")
            print("|"'货品数量:', item.quantity, "|", '货品名称:', product, "|", '货品单位名称:', product.unit.name,
                  "|", "货品类型id:",
                  product.unit.unit_type, "|")
            if (item.product_price is not None) and (item.before_weight is not None) and (item.quantity is not None):
                if product and product.unit.name != '克' and product.unit.unit_type == 2:
                    purchase_amount = float(item.product_price) * float(item.before_weight) * float(item.quantity)
                else:
                    purchase_amount = float(item.product_price) * float(item.quantity)
                total_last_week_purchase_amount += purchase_amount
            else:
                # 如果有任何一个值为 None，则跳过这次循环
                continue
        purchase_count = queryset.count()
        return total_last_week_purchase_amount, purchase_count

    """
    if item.product.unit_name!='克' and item.product.unit_type=='称重单位':
        item.product_price * item.before_weight * item.quantity
    else  item.product_price * item.quantity
    """

    def get_yesterday_purchase_summary(self, instance):
        created_at = self.context.get('created_at')
        yesterday_date = created_at.date() - timedelta(days=1)  # 获取前一天的日期
        queryset = instance.filter(stock_in_time__date=yesterday_date)
        # purchase_amount = queryset.aggregate(total_amount=Sum('product_price'))['total_amount'] or 0
        total_purchase_amount = 0
        for item in queryset:
            product = item.product
            print("|-----------------------------------------------------------------|")
            print("|"'货品数量:', item.quantity, "|", '货品名称:', product, "|", '货品单位名称:', product.unit.name,
                  "|", "货品类型id:",
                  product.unit.unit_type, "|")
            if (item.product_price is not None) and (item.before_weight is not None) and (item.quantity is not None):
                if product and product.unit.name != '克' and product.unit.unit_type == 2:
                    purchase_amount = float(item.product_price) * float(item.before_weight) * float(item.quantity)
                else:
                    purchase_amount = float(item.product_price) * float(item.quantity)
                total_purchase_amount += purchase_amount
            else:
                # 如果有任何一个值为 None，则跳过这次循环
                continue
        purchase_count = queryset.count()
        return total_purchase_amount, purchase_count

    def get_current_month_purchase_summary(self, instance):
        created_at = self.context.get('created_at')
        current_month = created_at.month
        current_year = created_at.year
        queryset = instance.filter(stock_in_time__year=current_year, stock_in_time__month=current_month)
        # 遍历采购记录，获取每个记录关联的产品名称和数量
        current_month_total_purchase_amount = 0
        for item in queryset:
            product = item.product
            print("|-----------------------------------------------------------------|")
            print("|"'货品数量:', item.quantity, "|", '货品名称:', product, "|", '货品单位名称:', product.unit.name,
                  "|", "货品类型id:",
                  product.unit.unit_type, "|")
            if (item.product_price is not None) and (item.before_weight is not None) and (item.quantity is not None):
                if product and product.unit.name != '克' and product.unit.unit_type == 2:
                    purchase_amount = float(item.product_price) * float(item.before_weight) * float(item.quantity)
                else:
                    purchase_amount = float(item.product_price) * float(item.quantity)
                current_month_total_purchase_amount += purchase_amount
            else:
                # 如果有任何一个值为 None，则跳过这次循环
                continue
        return current_month_total_purchase_amount


class SaleAmountQuantitySerializer(serializers.Serializer):
    today_sale_amount = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)
    today_sale_count = serializers.IntegerField(read_only=True)
    yesterday_sale_amount = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)
    yesterday_sale_count = serializers.IntegerField(read_only=True)
    last_week_sale_amount = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)
    last_week_sale_count = serializers.IntegerField(read_only=True)
    current_month_sale_amount = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)

    def to_representation(self, instance):
        print('传过来了', instance)
        today_sale_amount, today_sale_count = self.get_today_sale_summary(instance)
        yesterday_sale_amount, yesterday_sale_count = self.get_yesterday_sale_summary(instance)
        last_week_sale_amount, last_week_sale_count = self.get_last_week_sale_summary(instance)
        current_month_sale_amount = self.get_current_month_sale_summary(instance)

        return {
            'today_purchase_amount': today_sale_amount,
            'today_purchase_count': today_sale_count,
            'yesterday_sale_amount': yesterday_sale_amount,
            'yesterday_sale_count': yesterday_sale_count,
            'last_week_purchase_amount': last_week_sale_amount,
            'last_week_purchase_count': last_week_sale_count,
            'current_month_sale_amount': current_month_sale_amount,
        }

    def get_today_sale_summary(self, instance):
        print(instance, 1111)
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        queryset = instance.filter(created_at__date=created_at_date)
        sale_amount = queryset.aggregate(total_amount=Sum('dish_price'))['total_amount'] or 0
        sale_count = queryset.aggregate(total_count=Sum('sales_quantity'))['total_count'] or 0
        return sale_amount, sale_count

    def get_last_week_sale_summary(self, instance):
        created_at = self.context.get('created_at')
        created_at_date = created_at.date()  # 获取创建日期的年月日
        last_week_start = created_at_date - timedelta(days=created_at_date.weekday() + 7)
        last_week_end = last_week_start + timedelta(days=6)
        queryset = instance.filter(created_at__date__range=[last_week_start, last_week_end])
        # queryset = SalesRecord.objects.filter(created_at__date__range=[last_week_start, last_week_end])
        # print(queryset)
        sale_amount = queryset.aggregate(total_amount=Sum('dish_price'))['total_amount'] or 0
        sale_count = queryset.aggregate(total_count=Sum('sales_quantity'))['total_count'] or 0
        return sale_amount, sale_count

    def get_yesterday_sale_summary(self, instance):
        created_at = self.context.get('created_at')
        yesterday_date = created_at.date() - timedelta(days=1)  # 获取前一天的日期
        queryset = instance.filter(created_at__date=yesterday_date)
        sale_amount = queryset.aggregate(total_amount=Sum('dish_price'))['total_amount'] or 0
        sale_count = queryset.aggregate(total_count=Sum('sales_quantity'))['total_count'] or 0
        return sale_amount, sale_count

    def get_current_month_sale_summary(self, instance):
        created_at = self.context.get('created_at')
        current_month = created_at.month
        current_year = created_at.year
        queryset = instance.filter(created_at__year=current_year, created_at__month=current_month)
        total_sale_amount = queryset.aggregate(total_amount=Sum('dish_price'))['total_amount'] or 0
        return total_sale_amount


# class InventoryTrendSerializer(serializers.ModelSerializer):
#
#     class Meta:
#         model = Inventory
#         fields = '__all__'
class InventoryTrendSerializer(serializers.Serializer):
    date = serializers.DateField()
    product_name = serializers.CharField()
    day_of_week = serializers.CharField()
    value = serializers.DecimalField(max_digits=10, decimal_places=2)

    def to_representation(self, instance):
        # 如果 instance 为空，则直接返回空字典
        if not instance:
            return {}
        # 将日期作为 categories
        categories = list(instance.keys())
        categories.sort()  # 排序日期

        # 将数据转换成列表形式
        data_list = [instance[category] if instance[category] is not None else 0 for category in categories]

        # 构建 series 字典
        series = [{'name': '采购金额', 'data': data_list}]

        # 构建最终的结果字典
        result = {'categories': categories, 'series': series}
        print(result)

        return result

        # return {'data': result}  # 直接返回字典，包含了数据列表


class DishSerializer(serializers.ModelSerializer):
    class Meta:
        model = Dish
        fields = ('name',)


class SalesTrendSerializer(serializers.Serializer):
    date = serializers.DateField()
    product_name = serializers.CharField(source='dish.name')  # 使用 source 指定对应菜品的名称
    day_of_week = serializers.CharField()
    value = serializers.DecimalField(max_digits=10, decimal_places=2)

    def to_representation(self, instance):
        # 如果 instance 为空，则直接返回空字典
        if not instance:
            return {}
        # 将日期作为 categories
        categories = list(instance.keys())
        categories.sort()  # 排序日期

        # 将数据转换成列表形式
        data_list = [instance[category] if instance[category] is not None else 0 for category in categories]

        # 构建 series 字典
        series = [{'name': '销售金额', 'data': data_list}]

        # 构建最终的结果字典
        result = {'categories': categories, 'series': series}
        print(result)

        return result
